/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package wyse.server.web;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.logging.Logger;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

/**
 * Root class of the webserver
 * @author WK
 */
public class WebServer {
    /*
     * Ctor
     */
    public WebServer(String[] args) {
        parseCmdLine(args);

        initialize();
    }

    /*
     * Starts the server
     */
    public void start() throws Exception {
        mServer.start();
        mServer.join();
    }

    /*
     * Stops the server
     */
    public void stop() {
        if(mServer.isRunning()) {
            try {
                mServer.stop();
            } catch (Exception ex) {
            }
        }
    }

    /*
     * Initializes the server
     */
    private void initialize() {
        // obtain the root directory
        
        String wyseWebRoot = System.getenv("WYSE_WEB_ROOT");
        if(wyseWebRoot == null)
            mServerRootDir = new File(".");
        else {
            mServerRootDir = new File(wyseWebRoot);
            if(!mServerRootDir.isDirectory()) {
                sLogger.warning("WYSE_WEB_ROOT directory does not exist. Using the current directory.");
                mServerRootDir = new File(".");
            }
        }

        readConfig();

        setupJetty();
    }

    /*
     * Sets up Jetty
     */
    private void setupJetty() {
        mServer = new Server();

        // connectors

        SelectChannelConnector defaultConnector = new SelectChannelConnector();
        defaultConnector.setPort(mPublicPort);
        defaultConnector.setName("default");
        mServer.addConnector(defaultConnector);

        SelectChannelConnector adminConnector = new SelectChannelConnector();
        adminConnector.setPort(mAdminPort);
        adminConnector.setHost("localhost");
        adminConnector.setName("admin");
        mServer.addConnector(adminConnector);

        // client (public) interface

        ContextHandler clientHandler = new ContextHandler();
        clientHandler.setContextPath("/");

        ResourceHandler clientResHandler = new ResourceHandler();
        clientResHandler.setResourceBase(new File(mServerRootDir, "Client").toString());
        clientResHandler.setWelcomeFiles(new String[] { "index.html" });

        clientHandler.setHandler(clientResHandler);

        ServletContextHandler clientServletContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
        clientServletContext.setContextPath("/ws");

        WebSocketProxyServlet gameProxyServlet = new WebSocketProxyServlet(mWysePort);
        clientServletContext.setClassLoader(Thread.currentThread().getContextClassLoader());
        clientServletContext.addServlet(new ServletHolder(gameProxyServlet), "/Proxy");
        clientServletContext.addServlet(new ServletHolder(new TestServlet()), "/Test");

        ContextHandlerCollection clientContexts = new ContextHandlerCollection();
        clientContexts.setHandlers(new Handler[] { clientHandler, clientServletContext} );

        // admin interface

        ContextHandler adminHandler = new ContextHandler();
        adminHandler.setContextPath("/Server");

        ResourceHandler adminResHandler = new ResourceHandler();
        adminResHandler.setResourceBase(new File(mServerRootDir, "Server").toString());
        adminResHandler.setWelcomeFiles(new String[] { "index.html" });

        AdminIntfHandler adminIntfHandler = new AdminIntfHandler();
        adminIntfHandler.setHandler(adminResHandler);

        adminHandler.setHandler(adminIntfHandler);
        
        // main handlers

        HandlerList topHandlerList = new HandlerList();
        topHandlerList.addHandler(adminHandler);
        topHandlerList.addHandler(clientContexts);
        topHandlerList.addHandler(new DefaultHandler());

        mServer.setHandler(topHandlerList);
    }

    /*
     * Reads the configuration file
     */
    private void readConfig() {
        File cfgFile = new File(mServerRootDir, "wyse.server.web.properties");
        if(!cfgFile.isFile()) {
            sLogger.warning("No wyse.server.web.properties found in the root directory - using defaults");
            return;
        }

        FileInputStream fs = null;
        try {
            fs = new FileInputStream(cfgFile);
            Properties props = new Properties();
            props.load(fs);

            String propval;

            // public http port
            if((propval = props.getProperty("http.port.public")) != null) {
                try {
                    mPublicPort = Integer.parseInt(propval);
                } catch(NumberFormatException fe) {
                }
            }

            // administration interface port
            if((propval = props.getProperty("http.port.admin")) != null) {
                try {
                    mAdminPort = Integer.parseInt(propval);
                } catch(NumberFormatException fe) {
                }
            }

            // WYSE server port
            if((propval = props.getProperty("game.server.port")) != null) {
                try {
                    mWysePort = Integer.parseInt(propval);
                } catch(NumberFormatException fe) {
                }
            }

        } catch(IOException e) {
            sLogger.warning("Configuration file loading failed");
        } finally {
            try {
                if(fs != null)
                    fs.close();
            } catch(IOException ee) {
            }
        }
    }

    /*
     * Parses the command line
     */
    private void parseCmdLine(String[] args) {
    }

    private int mWysePort = 666;
    private int mPublicPort = 80;
    private int mAdminPort = 8080;

    private File mServerRootDir;
    private Server mServer;

    private static final Logger sLogger = Logger.getLogger(WebServer.class.getName());
}
